package com.syf.core.service.run;

import com.syf.core.service.SyService;
import com.syf.core.service.run.chain.ServiceExecutionChain;
import com.syf.core.service.run.chain.ServiceExecutionChainFactory;
import com.syf.core.service.run.chain.ServicePrePostHandle;
import com.syf.core.service.run.chain.impl.DefaultServicePrePostChain;
import com.syf.core.utils.classscan.ScanClassFromClassPath;
import com.syf.core.utils.classscan.TypeClassFilter;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 根据注解，获取配置的service前后处理类，最终生成service执行链
 */
public class DefaultServiceExecutionChainFactory implements ServiceExecutionChainFactory {
    /**
     * 类扫描基础路径
     */
    private final String scanBaseDir;

    /**
     * key为交易码
     */
    private final ConcurrentHashMap<SyService, ServiceExecutionChain> cachedExecutionChainStorage;

    /**
     * 业务系统定义的service前后处理集合
     */
    private final List<ServicePrePostHandle> prePostHandleList;

    public DefaultServiceExecutionChainFactory(String scanBaseDir) {
        this.scanBaseDir = scanBaseDir;
        cachedExecutionChainStorage = new ConcurrentHashMap<>();
        prePostHandleList = new ArrayList<>();

        // 自动扫描加载service前后处理器.
        loadServicePrePostHandles();
    }

    /**
     * serviceList请确保为single类型的service
     */
    @Override
    public void cachedServiceExecutionChains(Set<SyService> serviceList) {
        for (SyService service : serviceList) {
            ServiceExecutionChain chain = new DefaultServicePrePostChain(service, prePostHandleList);
            cachedExecutionChainStorage.put(service, chain);
        }
    }

    /**
     * single类型的service的chain才会缓存
     */
    @Override
    public ServiceExecutionChain getServiceExecutionChain(boolean isSingle, SyService service) {
        ServiceExecutionChain chain = cachedExecutionChainStorage.get(service);
        if (chain == null) {
            chain = new DefaultServicePrePostChain(service, prePostHandleList);
            if (isSingle) {
                cachedExecutionChainStorage.put(service, chain);
            }
        }

        return chain;
    }

    /**
     * 扫描scanBaseDir下所有ServicePrePostHandle的子类
     */
    private void loadServicePrePostHandles() {
        ScanClassFromClassPath scanHandler = new ScanClassFromClassPath(new TypeClassFilter(ServicePrePostHandle.class));
        Set<Class<?>> packageAllClasses = scanHandler.getPackageAllClasses(scanBaseDir, true);
        for (Class<?> clazz : packageAllClasses) {
            Class<ServicePrePostHandle> handleClass = (Class<ServicePrePostHandle>) clazz;
            ServicePrePostHandle prepostHandle;
            try {
                prepostHandle = handleClass.newInstance();
            } catch (InstantiationException | IllegalAccessException e) {
                throw new RuntimeException("构建ServicePrePostHandle对象实例出现异常", e);
            }
            prePostHandleList.add(prepostHandle);
        }

        // order越小，排队在前
        prePostHandleList.sort((o1, o2) -> o1.getOrder() < o2.getOrder() ? -1 : 1);
    }
}
